package zdream.pmfield.test.stage.effect;

import org.junit.Before;
import org.junit.Test;

import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicInteger;

import zdream.pmfield.data.foe.Foe;
import zdream.pmfield.data.foe.FoeTemplate;
import zdream.pmfield.data.foe.MoveTemplate;
import zdream.pmfield.data.foe.Type;
import zdream.pmfield.stage.StageBuilderForTest;
import zdream.pmfield.stage.StageWrapper;
import zdream.pmfield.stage.buff.ailment.ParalysisBuff;
import zdream.pmfield.stage.message.RollReportMessage;
import zdream.pmfield.stage.message.FoeAddBuffMessage;
import zdream.pmfield.storage.FoeTemplateStorage;
import zdream.pmfield.test.utils.ResourceConstant;
import zdream.pmfield.test.utils.StageConstant;

import static org.junit.Assert.*;

/**
 * @author Zdream
 * @date 2023-11-24
 * @since 0.0.1
 */
public class TypeBuffCase {
	FoeTemplateStorage storage;

	@Before
	public void before() {
		storage = new FoeTemplateStorage();
		storage.load();
		storage.loadMovesInResource(ResourceConstant.RES_PATH_TEST_MOVES_JSON);
	}

	@Test
	public void testSameTypeAttackBonus() {
		MoveTemplate moveWith100RateFix = storage.findMoveById(10000010, 1);
		assertEquals(moveWith100RateFix.name, "肯定成功");
		assertEquals(moveWith100RateFix.mainType(), Type.NORMAL);

		final FoeTemplate foeTemplate19 = storage.findFoeById(19);
		assertArrayEquals(foeTemplate19.types, new Type[] {Type.NORMAL});

		final FoeTemplate foeTemplate10 = storage.findFoeById(10);
		assertArrayEquals(foeTemplate10.types, new Type[] {Type.NORMAL});

		Foe foe1 = Foe.builder(foeTemplate19)
				.withLevel(20)
				.withMove(moveWith100RateFix)
				.build();
		Foe foe2 = Foe.builder(foeTemplate10)
				.withLevel(20)
				.withMove(moveWith100RateFix)
				.build();
		final StageWrapper wrapper = StageBuilderForTest.builder()
				.putFoeToOneSide(foe1)
				.putFoeToAnotherSide(foe2)
				.withStorage(storage)
				.buildWrapper();

		AtomicInteger count = new AtomicInteger(0);

		wrapper.onDefaultActionRequest();
		wrapper.printBeforeHandleMessage();
		wrapper.onMessage(RollReportMessage.class, reportMessage -> {
			if (!StageConstant.ROLL_TITLE_ACTION.equals(reportMessage.title)) {
				return;
			}
			assertTrue(reportMessage.rolls.length == 1);

			// 本系加成为多一个骰子
			assertTrue(reportMessage.moreRolls.length == 1);

			count.incrementAndGet();
		});

		wrapper.runUntil(stage0 -> count.get() >= 10);
	}

	@Test
	public void testTypeBonusNotWorkingWhenParalysis() {
		MoveTemplate moveWith100RateFix = storage.findMoveById(10000010, 1);
		assertEquals(moveWith100RateFix.name, "肯定成功");
		assertEquals(moveWith100RateFix.mainType(), Type.NORMAL);
		MoveTemplate paralysisMove = storage.findMoveById(10000012, 1);
		assertEquals(paralysisMove.name, "肯定麻痹");

		final FoeTemplate foeTemplate19 = storage.findFoeById(19);
		assertArrayEquals(foeTemplate19.types, new Type[] {Type.NORMAL});

		final FoeTemplate foeTemplate10 = storage.findFoeById(10);
		assertArrayEquals(foeTemplate10.types, new Type[] {Type.NORMAL});

		Foe foe1 = Foe.builder(foeTemplate19)
				.withLevel(20)
				.withMove(paralysisMove)
				.build();
		Foe foe2 = Foe.builder(foeTemplate10)
				.withLevel(20)
				.withMove(moveWith100RateFix)
				.build();
		final StageWrapper wrapper = StageBuilderForTest.builder()
				.putFoeToOneSide(foe1)
				.putFoeToAnotherSide(foe2)
				.withStorage(storage)
				.buildWrapper();

		AtomicBoolean paralysisApplied = new AtomicBoolean(false);
		AtomicBoolean checked = new AtomicBoolean(false);

		wrapper.onDefaultActionRequest();
		wrapper.onMessage(FoeAddBuffMessage.class, message -> {
			assertSame(message.foe.foe, foe2);
			assertTrue(message.buff.is(ParalysisBuff.CATEGORY));
			paralysisApplied.set(true);
		});
		wrapper.onMessage(RollReportMessage.class, reportMessage -> {
			if (!StageConstant.ROLL_TITLE_ACTION.equals(reportMessage.title)) {
				return;
			}
			if (!paralysisApplied.get()) {
				return;
			}
			if (reportMessage.foe.foe != foe2) {
				return;
			}
			assertTrue(reportMessage.rolls.length == 1);
			// 麻痹时本系加成失效
			assertTrue(reportMessage.moreRolls.length == 0);
			checked.set(true);
		});

		wrapper.runUntil(stage0 -> checked.get());
	}
}
